/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007-2008 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.projects.toolbox_basics_project.security.manager.impl;

import java.util.Set;

import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;

import com.genia.toolbox.security.bean.Permission;
import com.genia.toolbox.basics.exception.technical.TechnicalException;
import com.genia.toolbox.persistence.manager.PersistenceManager;
import com.genia.toolbox.projects.toolbox_basics_project.bean.model.User;
import com.genia.toolbox.projects.toolbox_basics_project.spring.manager.PermissionManager;
import com.genia.toolbox.projects.toolbox_basics_project.spring.manager.UserManager;

/**
 * implementation of {@link UserDetailsService}.
 */
public class UserDetailsServicesImpl
    implements UserDetailsService
{

  /**
   * the {@link UserManager} to use.
   */
  private UserManager userManager;

  /**
   * the {@link PermissionManager} to use.
   */
  private PermissionManager permissionManager;

  /**
   * the {@link PersistenceManager} to use.
   */
  private PersistenceManager persistenceManager;



  /**
   * Locates the user based on the username. In the actual implementation, the
   * search may possibly be case insensitive, or case insensitive depending on
   * how the implementaion instance is configured. In this case, the
   * <code>UserDetails</code> object that comes back may have a username that
   * is of a different case than what was actually requested..
   * 
   * @param username
   *          the username presented to the
   *          {@link  org.springframework.security.providers.dao.DaoAuthenticationProvider}
   * @return a fully populated user record (never <code>null</code>)
   * @throws UsernameNotFoundException
   *           if the user could not be found or the user has no
   *           GrantedAuthority
   * @throws DataAccessException
   *           if user could not be found for a repository-specific reason
   * @see org.springframework.security.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
   */
  public UserDetails loadUserByUsername(String username)
      throws UsernameNotFoundException, DataAccessException
  {
    try {
      User user = getUserManager().getUser(username);
      if (user == null) {
        throw new UsernameNotFoundException("Could not find user: " + username);
      }

      final Set<Permission> permissions = getPermissionManager().getPermissions(user);
      return new TrampolineUserDetails(getPersistenceManager().getCrossSessionManager().getCrossSessionObject(user), permissions.toArray(new GrantedAuthority[permissions.size()]));
    }
    catch (TechnicalException e) {
      throw new DataRetrievalFailureException(e.getMessage(), e);
    }
  }



  /**
   * returns the primitive value of the given {@link Boolean}. returns
   * <code>false</code> if the object is <code>null</code>.
   * 
   * @param bool
   *          the {@link Boolean} to retrieve the value for
   * @return the primitive value of the given {@link Boolean}
   */
  public boolean getBooleanValue(Boolean bool)
  {
    return ((bool != null) && bool);
  }



  /**
   * getter for the userManager property.
   * 
   * @return the userManager
   */
  public UserManager getUserManager()
  {
    return userManager;
  }



  /**
   * setter for the userManager property.
   * 
   * @param userManager
   *          the userManager to set
   */
  public void setUserManager(UserManager userManager)
  {
    this.userManager = userManager;
  }



  /**
   * getter for the permissionManager property.
   * 
   * @return the permissionManager
   */
  public PermissionManager getPermissionManager()
  {
    return permissionManager;
  }



  /**
   * setter for the permissionManager property.
   * 
   * @param permissionManager
   *          the permissionManager to set
   */
  public void setPermissionManager(PermissionManager permissionManager)
  {
    this.permissionManager = permissionManager;
  }



  /**
   * getter for the persistenceManager property.
   * 
   * @return the persistenceManager
   */
  public PersistenceManager getPersistenceManager()
  {
    return persistenceManager;
  }



  /**
   * setter for the persistenceManager property.
   * 
   * @param persistenceManager
   *          the persistenceManager to set
   */
  public void setPersistenceManager(PersistenceManager persistenceManager)
  {
    this.persistenceManager = persistenceManager;
  }
}
